package com.pond.pond.service.impl;

import com.pond.common.core.utils.DateUtils;
import com.pond.pond.domain.Appointment;
import com.pond.pond.domain.AppointmentTimeSegment;
import com.pond.pond.mapper.AppointmentMapper;
import com.pond.pond.service.AppointmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 预约信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-06-09
 */
@Service
public class AppointmentServiceImpl implements AppointmentService
{
    @Autowired
    private AppointmentMapper appointmentMapper;

    /**
     * 查询预约信息
     * 
     * @param id 预约信息主键
     * @return 预约信息
     */
    @Override
    public Appointment selectAppointmentById(Long id)
    {
        return appointmentMapper.selectAppointmentById(id);
    }

    /**
     * 查询预约信息 by userId
     *
     * @param userId 用户id
     * @return 预约信息
     */
    @Override
    public List<Appointment> selectAppointmentByUserId(Long userId) {
        // 1. 查询用户的所有预约信息
        List<Appointment> appointmentList = appointmentMapper.selectAppointmentByUserId(userId);

        // 如果预约列表为空，直接返回
        if (appointmentList.isEmpty()) {
            return appointmentList;
        }

        // 2. 获取所有的预约 ID
        List<Long> appointmentIds = appointmentList.stream()
                .map(Appointment::getId)
                .collect(Collectors.toList());

        // 3. 根据预约 ID 获取所有相关的时间段信息
        List<AppointmentTimeSegment> allSegments = appointmentMapper.selectSegmentsByAppointmentIds(appointmentIds);

        // 4. 将时间段信息按照预约 ID 分组
        Map<Long, List<AppointmentTimeSegment>> segmentMap = allSegments.stream()
                .filter(segment -> segment.getAppointmentId() != null)
                .collect(Collectors.groupingBy(AppointmentTimeSegment::getAppointmentId));

        // 5. 将时间段信息封装到每个预约中
        for (Appointment appointment : appointmentList) {
            appointment.setTimeSegments(segmentMap.getOrDefault(appointment.getId(), new ArrayList<>()));
        }

        // 6. 更新每个时间段的状态
        updateSegmentStatusByTime(appointmentList);

        // 7. 更新每个预约的状态
        updateAppointmentStatusBySegments(appointmentList);

        return appointmentList;
    }


    // 改内层status
    public void updateSegmentStatusByTime(List<Appointment> appointmentList) {
        if (appointmentList == null || appointmentList.isEmpty()) return;

        LocalDateTime now = LocalDateTime.now();

        for (Appointment appointment : appointmentList) {
            List<AppointmentTimeSegment> segments = appointment.getTimeSegments();
            if (segments == null || segments.isEmpty()) continue;

            for (AppointmentTimeSegment segment : segments) {
                Integer status = segment.getStatus();
                if (status == null || (status != 1 && status != 5)) { // 只处理未签到的，排除已签到(1)和管理员确认签到(5)

                    LocalDate date = segment.getAppointmentDate();
                    LocalTime startTime = segment.getStartTime();
                    LocalTime endTime = segment.getEndTime();

                    if (date != null && startTime != null && endTime != null) {
                        LocalDateTime startDateTime = LocalDateTime.of(date, startTime);
                        LocalDateTime endDateTime = LocalDateTime.of(date, endTime);

                        if (now.isAfter(endDateTime)) {
                            // 当前时间超过预约结束时间，未签到 → 爽约
                            segment.setStatus(4);
                            appointmentMapper.setInsideStatus(segment.getId());
                        } else if (now.isAfter(startDateTime) && now.isBefore(endDateTime)) {
                            // 当前时间在预约时间段内，未签到也算爽约（可选：根据规则）
                            segment.setStatus(4);
                            appointmentMapper.setInsideStatus(segment.getId());
                        }
                        // 否则：时间未到，不修改 status
                    }
                }
            }
        }
    }


    // 改外层status
    public void updateAppointmentStatusBySegments(List<Appointment> appointmentList) {
        if (appointmentList == null || appointmentList.isEmpty()) return;

        for (Appointment appointment : appointmentList) {
            List<AppointmentTimeSegment> segments = appointment.getTimeSegments();
            if (segments == null || segments.isEmpty()) {
                continue; // 没有时间段就不处理
            }

            // 获取所有子状态，确保是 Integer 类型
            Set<Integer> statusSet = segments.stream()
                    .map(AppointmentTimeSegment::getStatus)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            if (statusSet.isEmpty()) {
                continue;
            }

            // 定义优先级：0 > 1 > 5 > 3 > 4
            List<Integer> priority = Arrays.asList(0, 1, 5, 3, 4);

            for (Integer p : priority) {
                if (statusSet.contains(p)) {
                    Map<String, Object> params = new HashMap<>();
                    params.put("id", appointment.getId());
                    params.put("status", p);
                    appointmentMapper.setStatus(params);
                    appointment.setStatus(p);
                    break;
                }
            }
        }
    }


    /**
     * 查询预约信息列表
     * 
     * @param query 预约信息
     * @return 预约信息
     */
    @Override
    public List<Appointment> selectAppointmentList(Appointment query) {
        List<Appointment> appointmentList = appointmentMapper.selectAppointmentList(query);
        if (appointmentList.isEmpty()) {
            return appointmentList;
        }

        // 拿到所有ids
        List<Long> appointmentIds = appointmentList.stream()
                .map(Appointment::getId)
                .collect(Collectors.toList());

        List<AppointmentTimeSegment> allSegments = appointmentMapper.selectSegmentsByAppointmentIds(appointmentIds);
        // 封装到各自 appointment 中
        Map<Long, List<AppointmentTimeSegment>> segmentMap = allSegments.stream()
                .filter(segment -> segment.getAppointmentId() != null)
                .collect(Collectors.groupingBy(AppointmentTimeSegment::getAppointmentId));

        // push进原来的数组
        for (Appointment appointment : appointmentList) {
            appointment.setTimeSegments(segmentMap.getOrDefault(appointment.getId(), new ArrayList<>()));
        }
        updateSegmentStatusByTime(appointmentList); // 设置内层 segment 状态
        updateAppointmentStatusBySegments(appointmentList); // 设置外层 appointment 状态
        return appointmentList;
    }


    public boolean isTimeConflict(LocalTime start1, LocalTime end1,
                                  LocalTime start2, LocalTime end2) {
        // 两个时间段冲突的条件是它们有重叠部分
        // 严格判断，边界不算冲突
        return start1.isBefore(end2) && start2.isBefore(end1);
    }


    public boolean hasDuplicateAppointmentSegment(Appointment appointment) {
        List<Appointment> appointmentList = selectAppointmentList(appointment);
        Long currentId = appointment.getId();

        if (appointmentList != null && !appointmentList.isEmpty()) {
            for (Appointment otherAppointment : appointmentList) {
                // 排除自己（编辑场景）
                if (currentId != null && currentId.equals(otherAppointment.getId())) {
                    continue;
                }

                for (AppointmentTimeSegment otherSegment : otherAppointment.getTimeSegments()) {
                    Long seatId1 = otherSegment.getSeatId();
                    LocalDate date1 = otherSegment.getAppointmentDate();
                    LocalTime startTime1 = otherSegment.getStartTime();
                    LocalTime endTime1 = otherSegment.getEndTime();

                    for (AppointmentTimeSegment currentSegment : appointment.getTimeSegments()) {
                        Long seatId2 = currentSegment.getSeatId();
                        LocalDate date2 = currentSegment.getAppointmentDate();
                        LocalTime startTime2 = currentSegment.getStartTime();
                        LocalTime endTime2 = currentSegment.getEndTime();

                        // 1. seatId 不同：跳过
                        if (!Objects.equals(seatId1, seatId2)) {
                            continue;
                        }

                        // 2. 日期不同：跳过
                        if (date1 == null || date2 == null || !date1.equals(date2)) {
                            continue;
                        }

                        // 3. 时间段冲突
                        if (startTime1 != null && endTime1 != null
                                && startTime2 != null && endTime2 != null
                                && isTimeConflict(startTime1, endTime1, startTime2, endTime2)) {
                            return true; // 冲突
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 新增预约信息
     *
     * @param appointment 预约信息
     * @return 结果
     */
    @Override
    public int insertAppointment(Appointment appointment) {
        boolean isChecked = false;
        isChecked = hasDuplicateAppointmentSegment(appointment);
        if(isChecked){
            throw new IllegalArgumentException("冲突的钓位或预约时间");
        }


        // 插入预约主表
        appointment.setCreateTime(new Date());
        int rows = appointmentMapper.insertAppointment(appointment);

        if (appointment.getTimeSegments() != null && !appointment.getTimeSegments().isEmpty()) {
            for (AppointmentTimeSegment segment : appointment.getTimeSegments()) {
                segment.setAppointmentId(appointment.getId()); // 设置主表 ID
            }
            appointmentMapper.insertTimeSegment(appointment.getTimeSegments());
        }
        return rows;
    }



    /**
     * 修改预约信息
     * 
     * @param appointment 预约信息
     * @return 结果
     */
    @Override
    public int updateAppointment(Appointment appointment)
    {
        if(appointment.getId() == null){
            throw new IllegalArgumentException("更新操作必须提供有效的预约ID");
        }

        boolean isChecked = false;
        isChecked = hasDuplicateAppointmentSegment(appointment);
        if(isChecked){
            throw new IllegalArgumentException("冲突的钓位或预约时间");
        }

        appointment.setUpdateTime(DateUtils.getNowDate());
        int rows = appointmentMapper.updateAppointment(appointment);
        // 删除旧的时间段记录
        appointmentMapper.deleteTimeSegmentsByAppointmentId(appointment.getId());

        // 插入新的时间段记录
        if (appointment.getTimeSegments() != null && !appointment.getTimeSegments().isEmpty()) {
            for (AppointmentTimeSegment segment : appointment.getTimeSegments()) {
                segment.setAppointmentId(appointment.getId());
            }
            appointmentMapper.insertTimeSegment(appointment.getTimeSegments());
        }
        return rows;
    }

    /**
     * 批量删除预约信息
     * 
     * @param ids 需要删除的预约信息主键
     * @return 结果
     */
    @Override
    public int deleteAppointmentByIds(Long[] ids) {
        if (ids == null || ids.length == 0) {
            throw new IllegalArgumentException("删除操作必须提供有效的预约ID");
        }
        // 先删除时间段（子表）记录
        for (Long id : ids) {
            appointmentMapper.deleteTimeSegmentsByAppointmentId(id);
        }
        // 再删除预约主表记录
        return appointmentMapper.deleteAppointmentByIds(ids);
    }


    /**
     * 删除预约信息信息
     * 
     * @param id 预约信息主键
     * @return 结果
     */
    @Override
    public int deleteAppointmentById(Long id)
    {
        if(id == null){
            throw new IllegalArgumentException("删除信息必须要传id");
        }
        appointmentMapper.deleteTimeSegmentsByAppointmentId(id);
        return appointmentMapper.deleteAppointmentById(id);
    }
}
